/** boot/setup.S 

	1. 获取光标等信息
	2. 进入保护模式
	3. 跳入 head 
*/	
	.code16

#include <linux/config.h>

.equ InitSeg, 	DEF_INITSEG
.equ SetupSeg, 	DEF_SETUPSEG
.equ SysSeg, 	DEF_SYSSEG

	ljmp $SetupSeg, $start
start:
	mov $InitSeg, %ax 
	mov %ax, %ds 
	
	# get externed memory size
	mov $0x88, %ah 
	int $0x15
	mov %ax, %ds:2

    # set keyboard repeat rate to the max
    mov $0x0305, %ax 
    xor %bx, %bx 
    int $0x16

	# EGA/VGA
	mov $0x12, %ah
	mov $0x10, %bl 
	int $0x10
	mov %ax, %ds:8
	mov %bx, %ds:10
	mov %cx, %ds:12
	mov $0x5019, %ax 
	mov %ax, %ds:14

	# save cursor pos
	mov $0x03, %ah 
	xor %bh, %bh 
	int $0x10
	mov %dx, %ds:0	# 0x9000:0

	# get video-card data
	mov $0x0f, %ah 
	int $0x10
	mov %bx, %ds:4
	mov %ax, %ds:6

	# get hd0 data
	mov $0x0000, %ax 
	mov %ax, %ds 
	lds %ds:4*0x41, %si 
	mov $InitSeg, %ax 
	mov %ax, %es 
	mov $0x0080, %di 
	mov $0x10, %cx 
    cld 
	rep 
	movsb 

	# get hd1 data
	mov $0x0000, %ax 
	mov %ax, %ds 
	lds %ds:4*0x46, %si 
	mov $InitSeg, %ax 
	mov %ax, %es 
	mov $0x0090, %di 
	mov $0x10, %cx 
    cld 
	rep 
	movsb 

	# check hd1
	mov $0x1500, %ax 
	mov $0x81, %dl 
	int $0x13
	jc no_disk1 
	cmp $3, %ah 
	je is_disk1 
no_disk1:
	mov $InitSeg, %ax 
	mov %ax, %es 
	mov $0x0090, %di 
	mov $0x10, %cx 
	mov $0x00, %ax 
    cld 
	rep 
	stosb 
is_disk1:

	# protected mode
	cli 

	mov $0x0000, %ax 
	cld 
do_move:
	mov %ax, %es 
	add $0x1000, %ax 
	cmp $0x9000, %ax 
	jz end_move
	mov %ax, %ds 
	sub %di, %di 
	sub %si, %si 
	mov $0x8000, %cx 
	rep 
	movsw 
	jmp do_move
end_move:
	mov %cs, %ax 
	mov %ax, %ds 
	lidt idt_48
	lgdt gdt_48

	# A20
	inb $0x92, %al 
	orb $0x02, %al 
	outb %al, $0x92

	# 8259A
	mov $0x11, %al 	# ICW4 needed, cascade mode, level-triggered
	out %al, $0x20
	.word 0x00eb, 0x00eb 
	out %al, $0xa0
	.word 0x00eb, 0x00eb

	mov $0x20, %al 	# 0x20-27
	out %al, $0x21 
	.word 0x00eb, 0x00eb 
	mov $0x28, %al 	# 0x28-2f
	out %al, $0xa1
	.word 0x00eb, 0x00eb 	

	mov $0x04, %al 	# 8259a-1 master
	out %al, $0x21
	.word 0x00eb, 0x00eb
	mov $0x02, %al 	# 8259a-2 slave
	out %al, $0xa1
	.word 0x00eb, 0x00eb

	mov $0x01, %al	# 8086 mode
	out %al, $0x21
	.word 0x00eb, 0x00eb 
	out %al, $0xa1 
	.word 0x00eb, 0x00eb

	mov $0xff, %al 
	out %al, $0x21
	.word 0x00eb, 0x00eb 
	out %al, $0xa1

	mov %cr0, %eax 
	bts $0, %eax 	# set PE bit
	mov %eax, %cr0

	jmp $8, $0		# jmp head 8:0

gdt:
	.word 0,0,0,0	# null

	.word 0x07ff	# limit 8M
	.word 0x0000	# base address 0
	.word 0x9a00	# code read/exec
	.word 0x00c0	# granularity=4K, 386

	.word 0x07ff
	.word 0x0000
	.word 0x9200	# data read/write
	.word 0x00c0

gdt_48:
	.word 0x800		# limit 256 entries
	.word gdt+512, 0x9	# gdt base = 0x9XXXX

idt_48:
	.word 0
	.word 0,0
